//图片组件
/* import 'package:flutter/material.dart';
void main () => runApp(MyApp());

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context ){
      return MaterialApp(
        title:'Text widget',
        home:Scaffold(
          body:Center(
          child:Container(
            // child:Image.network('https://upload-images.jianshu.io/upload_images/5361063-e413832da0038304.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/800'),
            child:Image.network('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fyouimg1.c-ctrip.com%2Ftarget%2Ftg%2F035%2F063%2F726%2F3ea4031f045945e1843ae5156749d64c.jpg&refer=http%3A%2F%2Fyouimg1.c-ctrip.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625303183&t=c2132147ff65d46285bc713e53c503e7'),
            width:300.0,
            height:200.0,
            color: Colors.lightBlue,
          ),
          ),
        ),
      );
  }
} */
/* import "package:flutter/material.dart";
void main ()=> runApp(MyApp());

class MyApp extends StatelessWidget{
  @override 
  Widget build(BuildContext context){
    return MaterialApp(
      title:'Text widget',
      home:Scaffold(
        body:Center(
          child: Container(
            child: Image.network("https://gimg2.baidu.com"),
            width:300.0,
            height:200.0,
            color:Colors.lightBlue
          ),
        )
      )
    );
  }
} */
//动态列表渲染
// import 'package:flutter/material.dart';
// void main()=>{
//   runApp(MyApp(
//     items:List.generate(500, (index) => '测试item$index')
//   ))
// };
//
// class MyApp extends StatelessWidget{
//   final List<String> items;
//   MyApp({Key key,@required this.items}):super(key:key);
//   @override
//   Widget build(BuildContext context){
//     return MaterialApp(
//       home:Scaffold(
//         body: Center(
//           child:ListView.builder(
//             itemCount: items.length,
//             itemBuilder: (context,index){
//               return ListTile(
//                 // title: Text(`${items[index]}`),
//                 // title:Text('${items[index]}'),
//                 title:Text('${items[index]}')
//               );
//             }
//           )
//         ),
//       )
//     );
//   }
// }

//网格组件使用
/* import 'package:flutter/material.dart';
void main()=>{
  runApp(
    MyApp()
  )
};
class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      home:Scaffold(
        body:Container(
          padding:const EdgeInsets.all(10.0),
          child: MyGridView(),
        )
        
      )
    );
  }
}

class MyGridView extends StatelessWidget{

  @override
  Widget build(BuildContext context){
    return Center(
      child: GridView.count(
        crossAxisSpacing: 10.0,//不包括两边
        mainAxisSpacing: 10.0,//不包括两边
        crossAxisCount:2,
        childAspectRatio:0.7,//宽高比
        children:<Widget>[
            new Image.network('http://img5.mtime.cn/mt/2018/10/22/104316.77318635_180X260X4.jpg',fit: BoxFit.cover),
            new Image.network('http://img5.mtime.cn/mt/2018/10/10/112514.30587089_180X260X4.jpg',fit: BoxFit.cover),
            new Image.network('http://img5.mtime.cn/mt/2018/11/13/093605.61422332_180X260X4.jpg',fit: BoxFit.cover),
            new Image.network('http://img5.mtime.cn/mt/2018/11/07/092515.55805319_180X260X4.jpg',fit: BoxFit.cover),
            new Image.network('http://img5.mtime.cn/mt/2018/11/21/090246.16772408_135X190X4.jpg',fit: BoxFit.cover),
            new Image.network('http://img5.mtime.cn/mt/2018/11/17/162028.94879602_135X190X4.jpg',fit: BoxFit.cover),
            new Image.network('http://img5.mtime.cn/mt/2018/11/19/165350.52237320_135X190X4.jpg',fit: BoxFit.cover),
            new Image.network('http://img5.mtime.cn/mt/2018/11/16/115256.24365160_180X260X4.jpg',fit: BoxFit.cover),
            new Image.network('http://img5.mtime.cn/mt/2018/11/20/141608.71613590_135X190X4.jpg',fit: BoxFit.cover),
        ]
      ),
    );
  }
} */
import 'package:flutter/material.dart';
// import 'dart:convert';
//抽象的产品类
class Product {
  final String title;
  final String description;
  Product(this.title, this.description);
}

void main() => {
      // runApp(MaterialApp(//项目入口必须有MaterialApp函数
      //   title: '页面返回带回数据',
      //   // home: MyColumnContainer()
      //   home: MyFirstPage(
      //       products: List.generate(50,
      //           (index) => Product('商品${index + 1}', '商品描述:这是商品${index + 1}'))),
      // ))
      runApp(MyApp())
    };

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            body: Center(
      child: Container(
          // child: MyCard(),
          child: MyRowContainer(),
          alignment: Alignment.center,
          color: Colors.lightBlue,
          margin: const EdgeInsets.fromLTRB(10, 0, 10, 0),
          // width:400.0,
          height: 500.0),
    )));
  }
}

//水平布局

class MyRowContainer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(children: <Widget>[
      RaisedButton(
        onPressed: () {
          //数据类型:1.num(init,double) 2.String 3.bool 4.List 5.Map 6.Runes
          //变量分为:
            //一.静态变量:
              //1.显性 例如: String name = '张三';
              //2.隐性 var name = '张三';
            //二.动态变量 dynamic Object 声明的
            //注意:静态变量数据类型一旦确定不可改变,动态类型可改变数据类型
                //1.d
                // String name = '张三';
                // print(name);
                // num total = 1.1555555555555;
                // print(total);
                // var myhobbly = '打篮球,窜窜';
                // print(myhobbly);
                // dynamic age = 18;
                // print(age);
                // age = '-------:十八岁';
                // print(age);
                // Object tall = 1.8;
                // print(tall);
                // tall = '--------:一米八';
                // print(tall);

          //特别说明 当用var 声明时有来种情况:1.当声明不初始化赋值,后面赋值类型不受限制,例如:var color; color=true;color='red';
                                            //2.当声明且初始化赋值,此时类型已经确定,不能赋值其他类型的,例如:var color = 'red';color=true;报错
          //情况一.                                
            // var mynum; 
            // mynum=2;
            // mynum='3';
            // mynum=true;
            // print(mynum);//true;

          //情况二.   
          //   var mynum1=4;
            // mynum1='7';
            // print(mynum1);//报错

          //常量: 两种:final,const 两种
           //1.final运行时常量:可以是一个变量,但是只能赋值一次 ,2.const 编译时候常量:只能是等号右边的数字,字符窜,布尔值-只能赋值一次
            //  final mytime = new DateTime.now();
            //  print(mytime);
            //  const arr = const [1,3,4,5,7];
            //  print(arr);

        //字符串和num类型互换
          //1.字符转num
            // String total = '10';
            // int htotal = int.parse(total);
            // print(htotal);
            // String total = '10.1112';
            // double htotal = double.parse(total);
            // print(htotal);

          //2.num转字符串
              // int total = 10;
              // String htotal = total.toString();
              // print(htotal);
              // double total = 10.112566775;
              // String htotal = total.toStringAsFixed(3);
              // print(htotal);
            //扩展开:相关方法
              //(1).floor(向下取整),ceil(向上取整),round(四舍五入),abs(绝对值),toStringAsFixed(保留小数),toInt(转化为数字),isEven(是否是偶数),isOdd(是否为奇数) //(只有正数能使用奇,偶判断),toString
              // double num1 = 1.2222;
              // double num2=-1.99;3
              // int num3=66;
              // String mystr = "floor:${num1.floor()},floor-:${num2.floor()},ceil:${num1.ceil()},ceil:${num2.ceil()},round:${num1.round()},round-:${num2.round()},ads:${num2.abs()},toStringAsFixed:${num2.toStringAsFixed(1)},类型:${num2.toStringAsFixed(1) is num},偶数:${num3.isEven},奇数:${num3.isOdd}";
              // print(mystr);//floor:1,floor-:-2,ceil:2,ceil:-1,round:1,round-:-2,ads:1.99,toStringAsFixed:-2.0,类型:false,偶数:true,奇数:false
              
              // //随机数 nextInt(max)取值范围[max); 需要引入import "dart:math";
              // int getRandom(int min,int max){
              //   // return min + Random().nextInt(max - min + 1);
              //   return 1;
              // }
              // print("随机数:${getRandom(2,100)}");
          //位运算后面再看

          //字符串创建
          //1.单双引号
            // var mystring = '加油啊';
            // print(mystring);

          //2.多行字符窜声明可以使用类似python""",'''
            // String mystring1 = """明天就周五了,
            // 周末要到了""";
            // print(mystring1);

          //3.类似python 可以使用字符窜模板
            // var path = r'D:\workspace\code';
            // print(path);

          //4.类似Python，还可以在字符串字面值的前面加上`r`来创建原始字符串，则该字符串中特殊字符可以不用转义

          //5.字符窜可以使用+拼接
            // String mystring1 = '明天';
            // String mystring2 = '哈哈';
            // print(mystring1+mystring2);

          //6.可以使用类似js中的字符窜模板${} ,中括号可以省略
            // String myday = '星期四';
            // String mystring1 = "今天是$myday";
            // print(mystring1);

          //7.与java不同 ==用来比较字符串的内容
              //  print('加油'=='加油啊');

          //布尔类型 1.只有true,false俩种 2.默认值是null
            // bool myflag;
            // print(myflag);
          //字符串方法扩展
          //split-切割 substring-下标取值 startWith-是否以xx开头 endWith-是否以xx结尾 toUpperCase-转化成大写  toLowerCase-转小写 
            //indexOf-a字段在b字段中的下标 replaceFirst-用a替换b中的c,匹配的第一个 replaceAll ...,匹配替换全部  trim-去掉收尾空格 
            //contains-是否包含指定字符 .length-长度
            // String mystr11= 'https://gitee.com/chenzhenwei123/fresh-display/commits/master   ';
            // String res="总长:${mystr11.length},切割:1-${mystr11.split('/')},是否http开头:${mystr11.startsWith('http')},是否以空格结尾:${mystr11.endsWith('  ')},转化为大写:${mystr11.toUpperCase()},转化为小写:${mystr11.toLowerCase()},chenzhenwei下标:${mystr11.indexOf('chenzhenwei')},去除空格后长度:${mystr11.trim().length},替换一个c:${mystr11.replaceFirst('c','哈哈')},替换全部c:${mystr11.replaceAll('c','洗洗')},是否包含chenzhenwei:${mystr11.contains('chenzhenwei')}";
            // print(res);
            // String resStr="""
            //   总长:64,切割:1-[https:, , gitee.com, chenzhenwei123, fresh-display, commits, master   ],是否http开头:true,是否以空格结尾:true,转化为大写:HTTPS://GITEE.COM/CHENZHENWEI123/FRESH-DISPLAY/COMMITS/MASTER   ,转化为小写:https://gitee.com/chenzhenwei123/fresh-display/commits/master   ,chenzhenwei下标:18,去除空格后长度:61,替换一个c:https://gitee.哈哈om/chenzhenwei123/fresh-display/commits/master   ,替换全部c:https://gitee.洗洗om/洗洗henzhenwei123/fresh-display/洗洗ommits/master   ,是否 
            //   包含chenzhenwei:true
            // """;

          //列表类型
          //1.初始化
            //(1)不固定长度
              // List mylist = List();
              // print(mylist);
            //(2)固定长度
              // List mylist = List(2);
              // var myshow = "length:${mylist.length},,$mylist";
              // print(myshow);
            //(3)固定内容类型
              // List mylist = List<num>();
              // mylist.add('aa');
              // mylist.add(1);
              // mylist.add(2.111);
              // print(mylist);
            //(4)直接赋值
              // List mylist = [1,2];
              // mylist.add('222');
              // print(mylist);

          //2.常用字段
          //(1)length
          //(2)isEmpy,列表是否为空
            // List myList = List();
            // print(myList);
            // myList.add(211);
            // print(myList.isEmpty);

          //(3)isNotEmpy,列表是否有数据
            // List mylist = List();
            // mylist.add(3);
            // print(mylist.isNotEmpty);

          //3.添加数据
          //(1).固定长度类型,必须使用下标赋值,其他不可使用例如:add添加
            // List mylist = List(2);
            // mylist[0] = 2;
            // mylist[3]=3;
            // mylist.add('3');
            // print(mylist);
            
          //(2)非固定长度类型,不可使用下标赋值
          
          //(3).添加全部元素
            // List mylist1 = [1,2,34,5];
            // List mylist2 = List();
            // mylist2.addAll(mylist1);
            // var res = 'mylist1:$mylist1,,,mylist2:$mylist2';
            // print(res);

          //(4).像指定位置添加元素
            // List mylist1 = List();
            // mylist1.insert(2,'编号3');
            // print(mylist1);

            // List mylist = [1,23,5666];
            // mylist.insert(1,'哈哈哈');
            // print(mylist);
          //(5)List方法扩展
            //一.增加的数据的方法,这些方法都会改变原List
            //add(ele)-增加某个元素 addAll(list)-增加某个List insert(index,ele)-在下标index插入某个元素 insertAll(index,list)-在下标为index处插入某个list
            // List list1=[0,1,2,3,4];
            // List list2=['加','油','啊'];
            // List list3=[3];
            // List list4=['我','水'];
            // list1.add(5);
            // list2.insert(1,'水');
            // list3.addAll(list1);
            // list4.insertAll(1,list2); 
            // String mystr = 'list1:$list1;list2:$list2;list3:$list3;list4:$list4';
            // print(mystr);
            //-I/flutter (23260): list1:[0, 1, 2, 3, 4, 5];list2:[加, 水, 油, 啊];list3:[3, 0, 1, 2, 3, 4, 5];list4:[我, 加, 水, 油, 啊, 水]

            //二删除数据的方法5个
            //remove(ele)-删除list中指定元素 removeAt(index)-删除list中指定下标元素 clear()-清空list 
            //removeWhere((e)=>{return bool})-删除满足条件的元素(1.有满足条件的元素则删除,原list改变;2.无满足条件的返回原list)-没有啥用
            //removeRange(start,end)-[start,end),删除指定下标范围的元素,含头不含尾
            // List<int> list1=[0,1,2,3];
            // list1.remove(2);
            // List<int> list2=[3,4,5];
            // list2.removeAt(1);
            // List<int> list3=[2,2,2,2];
            // list3.clear();
            // List<int> list4=[6,7,8,9,10];
            // list4.removeWhere((item)=>item>=8);
            // List list5 =['明','天','周','三'];
            // list5.removeRange(1,4);
            // String str1='list1:$list1;list2:$list2;list3:$list3;list4:$list4;list5:$list5';
            // print(str1);
            //list1:[0, 1, 3];list2:[3, 5];list3:[];list4:[6, 7];list5:[明]

            //修改数据的方法5个-都是改变原list的方法
            //list[index]-利用索引赋值(用List()声明的list不可用索引赋值)
            //fillRange(start,end,ele)-用某个元素填充替换某个索引范围能的元素,[satrt,end)含头不含尾
            //replaceRange(start,end,list)-用某个list中(全部)元素依次替换指定索引范围内的元素,[satrt,end)含头不含尾
            //setRange(start,end,list)-用某个list中指定索引范围的元素替换原list中对应索引范围的元素,[satrt,end)含头不含尾
            //setAll(index,list)-用某个list的所以元素替换原list对应index的元素
            // List list1=[0,1,2,3,4];
            // List list2=[5,6,7,8];
            // List list3=[9,10,11,12];
            // List list4=[13,14,15,16];
            // list1.fillRange(2,5,'加加');
            // list2.replaceRange(2,3,['明','天','周','三']);
            // list3.setRange(0,3,['快','要','元','但','了']);
            // list4.setAll(3,['过']);//注意lis4.length必须大于(index+list.length),否则会报错
            // String mystr99 = 'list1:$list1;list2:$list2;list3:$list3;lis4:$list4';
            // print(mystr99);
            //list1:[0, 1, 加加, 加加, 加加];list2:[5, 6, 明, 天, 周, 三, 8];list3:[快, 要, 元, 12];lis4:[13, 14, 15, 过]

            //查询数据-8个方法
              //elementAt(index)-获取指定索引对应下标的元素,返回值:目标元素 //contains(ele)-List是否含有指定元素,返回值:true或false
              //indexOf(ele)-判断list中是否存在某个元素,返回值:1.存在返回对应下标 2.不存在返回-1
              //where(e=>bool)-相当于js中filter,筛选出满足条件的元素,以满足条件元素组成新list返回,返回值:满足条件元素组成的list
              //sublist(start,end)-同js用法,(start,end]含头不含尾,若参数只有一个某认(index,list.length),返回值:对应索引元素组成的新list
              //whereType()-从混合类型list中筛选出对应类型的Iterable
              //any(e=>bool)-list中是否有满足条件的元素,返回值:1.有,返回true,没有则返回false
              //every(e=>bool)-list中是否每个元素都满足条件,返回值:1.全部满足返回true,否返回false
              // List list1 = [1,2,3,4,5];
              // num num1 = list1.elementAt(3);
              // int flag = list1.indexOf(5);
              // List<Map> list2 = [{'name':'ming','age':'h12'},{'name':'hua','age':'13'}];
              // List<Map> list3 = list2.where((item){
              //   Map item1 = item;
              //   print(item1);
              //   return item['name']=='hua';
              // }).toList();
              // List list4 = list1.sublist(1,4);
              // List list5 = ['1',6,true,{'name':'hua'},00];
              // Iterable<int> num3 = list5.whereType();
              // Iterable<String> str1 = list5.whereType();
              // Iterable<Map> mymap = list5.whereType();
              // Iterable<bool> flag2 = list5.whereType();
              // List mylist1 = [];
              // num3.forEach((item){
              //   if(item is num){
              //     mylist1.add(item);
              //   }
              // });
              // bool flagany=list1.any((item){
              //   num mynum= item;
              //   return mynum >2;
              // });
              // bool flagevery = list1.every((item){
              //   num mynum = item;
              //   return mynum>2;
              // });
              // String target1 = 'num1:$num1;flag:$flag;list3:$list3;list4:$list4;list5:$list5;str1:$str1;num3:$num3;mymap:$mymap;flag2:$flag2;flagany:$flagany;flagevery:$flagevery;mylist1:$mylist1';
              // print(target1);
              // num1:4;flag:4;list3:[{name: hua, age: 13}];list4:[2, 3, 4];list5:[1, 6, true, {name: hua}, 0];str1:(1);num3:(6, 0);mymap:({name: hua});flag2:(true);flagany:true;flagevery:false;mylist1:[6, 0]

              //常用的List方法
              //forEach(e=>)-遍历list  map(item=>ele)-对list中每个元素进行操作,并以Iterable类型返回每一个元素
              //toSet()-将List类型转换为Set类型,作用主要是去重
              //asMap()-将List转换为以索引为key的Map类型
              //join(str)-将list用str拼接,返回拼接好的str
              //sort((left,right){left['age].compareTo(right['age'])})-排序,第一个参数left在前,则为从小到大,第二个参数在前则为从大到小,改变原list
              //shuffle()-随机改变list,改变原list
                // List list1=[{'age':18,'name':'hua'},{'age':20,'name':'hong'}];
                // List list2 = ['陈','振','伟'];
                // List list3 = list1.map((item){
                //   Map itemn= item;
                //   if(itemn['name']=='hong'){
                //     itemn['sex']='女';
                //   }else{
                //     itemn['sex']='男';
                //   }
                //   return itemn;
                // }).toList();
                // list1.forEach((item){
                //   print('age:${item["age"]}');
                //   // print(item);
                // });
                // Map listh = list2.asMap();
                // String str = list2.join('--');
                // list1.sort((left,right){
                //   return left['age'].compareTo(right['age']);
                // });
                // List list66=[9,8,7,6,5,4,3,6,9,3];
                // List list77 = [11,2,24,5,2,1,0];
                // list66.sort((left,right){
                //   return left.compareTo(right);
                // });
                // list77.sort((left,right){
                //   return right.compareTo(left);
                // });
                // list2.shuffle();
                // String result = 'lsit1:$list1;listh:$listh;str:$str;list3:$list3;list66:$list66;list77:$list77';
                // print(result);
                //  lsit1:[{age: 18, name: hua, sex: 男}, {age: 20, name: hong, sex: 女}];listh:{0: 伟, 1: 振, 2: 陈};str:陈--振--伟;
                //list3:[{age: 18, name: hua, sex: 男}, {age: 20, name: hong, sex: 女}];
                //list66:[3, 3, 4, 5, 6, 6, 7, 8, 9, 9];list77:[24, 11, 5, 2, 2, 1, 0]
          //List,Set,Map的深复制
            //注意:1.使用List.from(mulist1)复制只有子元素类型为string,num,bool时不影响原list
                //2.使用遍历方法
                //3.使用json.encode and json.decode 需要引入对应包:import 'dart:convert';
          //1.使用List.from(mulist1)
            // List mylist1 = [1,2,3,4,5,6];
            // List coty1 = List.from(mylist1);
            // coty1[0]=7;
            // String tests1="mylist1:${mylist1},coty1:$coty1";
            // print(tests1);//mylist1:[1, 2, 3, 4, 5, 6],coty1:[7, 2, 3, 4, 5, 6]

            // List mylist1=[{'age':'1'},{'age':'2'},{'age':'3'}];
            // List copy1 = List.from(mylist1);
            // copy1[0]['age']='7';
            // String test1 = "mylist1:$mylist1,copy1:$copy1";
            // print(test1);//2个list都被修改了mylist1:[{age: 7}, {age: 2}, {age: 3}],copy1:[{age: 7}, {age: 2}, {age: 3}]

          //2.使用遍历方法贝
            // List copyWithList(List list) {
            //   List copyList = [];
            //   for (var item in list)) {//item为元素和js中为下标不一样
            //     if (item is Map) {
            //       copyList.add(Map.from(item));
            //     } else if (item is List) {
            //       copyList.add(copyWithList(item));
            //     } else {
            //       copyList.add(item);
            //     }
            //   }
            //   return copyList;
            // }
            // List mylist1=[{'age':'1'},{'age':'2'},{'age':'3'}];
            // List copy1 = copyWithList(mylist1);
            // copy1[0]['age']='7';
            // String test1 = "mylist1:$mylist1,copy1:$copy1";
            // print(test1);//2个list都被修改了mylist1:[{age: 7}, {age: 2}, {age: 3}],copy1:[{age: 7}, {age: 2}, {age: 3}]
          //使用json.encode和json.decode需要引入包:import 'dart:convert';

          //3.使用json.encode and json.decode
            // List mylist1=[{'age':'1'},{'age':'2'},{'age':'3'}];
            // List mylist1 = [{'hobbly':[{'name':'篮球'}]},{'age':'1'},{'friends':[{'name':'hong'},{'name':'ming'}]}];
            // List copy1 = json.decode(json.encode(mylist1));
            // copy1[0]['hobbly'][0]['name']='王者';
            // copy1[1]['age']='一百岁';
            // String test1 = "mylist1:$mylist1,copy1:$copy1";
            // print(test1); //mylist1:[{age: 1}, {age: 2}, {age: 3}],copy1:[{age: 1}, {age: 一百岁}, {age: 3}]
            //原List不受影响 //mylist1:[{hobbly: [{name: 篮球}]}, {age: 1}, {friends: [{name: hong}, {name: ming}]}],copy1:[{hobbly: [{name: 王者}]}, {age: 1}, {friends: [{name: hong}, {name: ming}]}]
          
          //Set作用,复制,和List的相互转化
            //1.作用:一般用于List去重例如 List arr=[1,2,2,2,3]; Set testset = arr.toSet();得到{1,2,3};
            //2.复制用 Set.from(testset)
            //3.相互转换 List转换为Set List arr=[1]; Set myset = arr.toSet();   Set转List:Set mytest={1,2}; List mylist = mytest.toList();
              // List mylist=[2,2,2,3,456,6,6,7];
              // Set listset = mylist.toSet();
              // Set myset = Set();
              // myset.add('加油');
              // myset.add('周五');
              // Set copyset = Set.from(myset);
              // copyset.add('放假');
              // String str2 = "myset:$myset,copyset:$copyset,listset:${listset},copysetToList:${copyset.toList()}";
              // print(str2);
              // myset:{加油, 周五},copyset:{加油, 周五, 放假},listset:{2, 3, 456, 6, 7},copysetToList:[加油, 周五, 放假]

          //映射Map,声明,深复制
              //一.声明方式
                //1.字面量声明
                  // var gifts = {
                  //   'first' : 'partridge',
                  //   'second': 'turtledoves',
                  //   'fifth' : 'golden rings'
                  // };
                  // print(gifts);

              //2.new Map()
                // var myMap = new Map();
                // myMap['first']="11";
                // print(myMap);
                //{first: 11}

              //二.长度 myMap.length

              //三.取值 myMap['first'];
                // String mystr="${myMap.length}-----${myMap['first']}";
                // print(mystr);

              //深复制
                //1.当用Map.from()时并不是真正的深复制
                  // Map mymap = {
                  //   'name':'hong',
                  //   'age':18,
                  //   'tall':175,
                  //   'hobbly':[{'name':'篮球'},{'name':'足球'}]
                  // };
                  // Map testmap1=Map.from(mymap);
                  // // testmap1['name']='ming';
                  // testmap1['hobbly'][0]['name']='游戏';
                  // String mapstr="mamap:$mymap,testmap1:$testmap1";
                  // print(mapstr);//并不影响原map--mamap:{name: hong, age: 18, tall: 175},testmap1:{name: ming, age: 18, tall: 175}
                  //当原map为复杂数据时这种深复制还是会影响原map:
                  //mamap:{name: hong, age: 18, tall: 175, hobbly: [{name: 游戏}, {name: 足球}]},testmap1:{name: hong, age: 18, tall: 175, hobbly: [{name: 游戏}, {name: 足球}]}
                //2.使用 json.encode和json.decode
                    //注意:json.encode和json.decode对map不能进行深复制,但是对List可以,所以对于map深复制可以像如下将map转List利用json深复制然后再取回

                  // Map mymap = {
                  //   'name':'hong',
                  //   'age':18,
                  //   'tall':175,
                  //   'hobbly':[{'name':'篮球'},{'name':'足球'}]
                  // };
                  //转换为List深复制成功
                    // List townlist = [mymap];
                    // List copytwonlist = json.decode(json.encode(townlist));
                    // Map mymapcopy = copytwonlist[0];
                    // mymapcopy['hobbly'][0]['name']='打王者';
                    // String mapstr="mamap:$mymap,testmap1:$mymapcopy";
                    // //转换后深复制成功--mamap:{name: hong, age: 18, tall: 175, hobbly: [{name: 篮球}, {name: 足球}]},testmap1:{name: hong, age: 18, tall: 175, hobbly: [{name: 打王者}, {name: 足球}]}
                    // print(mapstr);
                  //直接用json,深复制不成功
                  // Map testmap1=json.decode(json.encode(mymap));
                  // Map testmap1=json.decode(json.encode(mymap));
                  // testmap1['name']='ming';
                  // testmap1['hobbly'][0]['name']='游戏';
                  // String mapstr="mamap:$mymap,testmap1:$testmap1";
          //校验和强制转化类型 as转换2个条件:1.num的子类型:double,init 2.值必须为要强制转化的类型
          // int number = 100;
          // double distance = 200.5;
          // num age = 18.3;
          // print(number is num);//true
          // print(distance is! int);//true
          // print(age as double);//18

          //Map常用属性和常用方法
            //常用属性:1.keys-获取所有key,得到的是Iterable类型,需要转换 2.values-获取所有value 3.isEmpty-是否为空 4.
            //常用方法:1.remove(key)-删除指定key项 2.addAll(map)-合同Map 3.containsValue(value)-map里是否存在值为value的项 4.map,forEach((key,value){}),every(),any()同list相识
            // Map mymap = {
            //   'age':18,
            //   'name':'hua',
            //   'addres':'guiyang',
            //   'sex':'nan'
            // };
            // Map mymap2 ={
            //   'school':'qinghua',
            //   'jia':'xiang'
            // };
            // List keyList = mymap.keys.toList();
            // List valList = mymap.values.toList();
            // bool empyflag = mymap2.isEmpty;
            // mymap2.remove('jia');
            // mymap.addAll(mymap2);
            // bool valueFlag = mymap.containsValue('guiyang');
            // mymap.forEach((key,val){
            //   print('$key:$val');
            // });
            // String mystr = 'mymap:$mymap;mymap2:$mymap2;keyList:$keyList;valList:$valList;emptyflag:$empyflag;valueFlag:$valueFlag';
            // print(mystr);
            // mymap:{age: 18, name: hua, addres: guiyang, sex: nan, school: qinghua};mymap2:{school: qinghua};keyList:[age, name, addres, sex];valList:[18, hua, guiyang, nan];emptyflag:false;valueFlag:true

          //函数: 
            //1.参数不受位置影响,定义的参数每个不必传且位置也不必和定义的一一对应默认值//add({num a,num b=3}) 传:add(a:1,3)
            //2.参数受位置影响,且定义了的每个参数必须穿,一一对应 add(num a,num b)
            //3.参数受位置影响,但是定义的参数不是全都要传,可以只穿前面几个,但是一定要按定义的位置对应传

            // add1({num a,String b='b'}){
            //   print('num:$a;string:$b');
            // }
            // add1(b:'1');//num:null;string:1
            // add2(num a,String str,num c){
            //   print('a:$a;str:$str;c:$c');
            // }
            // add2(2,'bb',9);//a:2;str:bb;c:9
            // add3([num a,num b,bool c=false]){
            //   print('a:$a;b:$b;c:$c');
            // }
            // add3(2);//a:2;b:null;c:false

            // gaojie(num a,num b,Function c,Function d){
            //   c(a);
            //   d(b);
            // }
            // Function print1 = (a){
            //   print('我是函数c:$a');
            // };
            // Function print2 = (a){
            //   print('我是函数d:$a');
            // };
            // gaojie(99,88,print1,print2);//我是函数c:99  我是函数d:88

          //class类使用
            //1.getter,setter类似于vue中computed属性,大多用于某个a = b x c;a依赖于b和c操作得到
              // var shiLi = Rectangle(1,2,3,4);
              // shiLi.right = 20;
              // shiLi.bottom = 2;
              // print('let:${shiLi.left};square:${shiLi.square};height:${shiLi.height};top:${shiLi.top};');
              // //let:17;square:-34
              // shiLi.height=-10;
              // shiLi.bottom = 2;//虽然height已经改变了,但是这里必须再执行一次bottom,对应的top才会重新计算
              // print('22-let:${shiLi.left};height:${shiLi.height};square:${shiLi.square};top:${shiLi.top};');
              // //22-let:17;height:-10;square:204;top:12; 

            //2.面向对象中的变量,搜索:--指向外面类
              // (1)getter setter属性-类似vue中computed属性
              //var liyi = TestBianLiang(99,'哈哈哈哈');
              // print('total:${liyi.total};_str1:${liyi._str1}');
              //total:99;_str1:哈哈哈哈
              // liyi.total=77;

              //(2)实例变量,分为普通变量和私有变量(用_开头),(并没有发现私有变量和普通变量有何差别)
              // liyi._str1 = '准备回去过年了';
              // print('111total:${liyi.total};_str1:${liyi._str1}');
              //111total:77;_str1:准备回去过年了

              //(3).final常量,即初始化后就不能改变的变量,特点:1.只有getter函数,没有setter函数
              // FinalDemoClass myfinaldemo = FinalDemoClass('暴富,美满幸福',99);
              // print('test1;mywant:${myfinaldemo.mywant};total:${myfinaldemo.total}');
              //设置mywant
              // myfinaldemo.mywant = '暴富,美满幸福,健康';//会报错,因为final声明的变量没有setter函数

              //(4).常量对象,特点:1.声明,实例,构造函数都要用const声明 2.常量构造函数必须是数字,字符串,布尔值(所以需要用const声明),且函数不能有函数体,但可以有初始化列表
              // const ConstDemo myconstdemo = const ConstDemo('哈哈哈');
              // print('myconstdemo:${myconstdemo.name}');

            //3.构造函数
              //(1).主构造,特点:1.一般默认柱构造函数和类名相同 2.如果没有声明主构造函数,会默认给一个和类名同名的无参构造函数 3.主构造函数不支持重载(即不能重复声明)
              //(2).命名构造函数,组成:类名.函数名 作用:1.为了解决主构造函数不能重载的问题(实际上普通函数也不能重载)
                // MingMin mymingdemo = MingMin('test1',77);
                // MingMin mymingdemo2 = MingMin('test1',77);
                // print('name:${mymingdemo.name};total:${mymingdemo.total}');
                // print('name:${mymingdemo2.name};total:${mymingdemo2.total}');
                //name:test1;total:77
                //使用命名构造函数创建实例
                // MingMin mymingdemo1 = MingMin.getDemo('test2');
                // print('name:${mymingdemo1.name};total:${mymingdemo1.total}');
                //name:test2;total:null
              //(3).重定向构造函数,将一个构造函数定向到另外一个函数中,':'后是被定向到的目标构造函数
              //(4).函数实例工厂:简而言之为了提升性能把构造函数创建的实例存起来,下次需要时直接从缓存中取
                //关键点:(1)用factory 修饰构造函数 (2)使用命名构造函数 (3)在主构造函数中进行逻辑判断,使用static 关键字声明存储实例的map
                // FactoryDemo testFactoryDemo = FactoryDemo('嘻嘻1');
                // print('name:${testFactoryDemo.name}');
                // //第一次创建实例 嘻嘻1
                // FactoryDemo testFactoryDemo1 = FactoryDemo('嘻嘻1');
                // print('name:${testFactoryDemo1.name}');
                //直接从缓存中拿 嘻嘻1

            //4.抽象方法,抽象类,接口(特别注意:抽象类不能够实例化,只能继承extends或者接口implements使用)
              //(1).抽象类抽象方法是用abstract修饰的方法和类,抽象方法包括普通方法,getter,setter即只对其进行声明,并没有具体提供具体的实现
                // Student myStudent = Student();
                // print('name:${myStudent.name()};age:${myStudent.age}');
                //name:222;age:null
              //(2)接口:在dart中每个类都隐含的定义了一个接口,所以dart中并没有关键字interface;interface(目前理解使用类型于extends继承,只是接口可以继承多个类(implements))
                // Student1 myStudent1 = Student1();
                // print('speck:${myStudent1.speck()};wrie:${myStudent1.write()}');
                //speck:i can specking;wrie:i can writing

            //5.类函数
              //(1)特点:类函数不会被继承;类函数需要用关键字static 修饰 ;类函数直接使用(类名.函数名调用)
                //直接类点,实例调用不了
                // String str1 = Car.calcTotal(3, 9);
                // print(str1);
                //总价格:27
                // Car car1 = Car('奔驰',5,9);
                // print('总价格:${car1.name},${car1.price}');
                //总价格:奔驰,5
                
                //特殊注意类函数也不会被继承,所以Benci中并没有calcTotal函数

            //6.类继承补充
              //(1)子类调用父类方法:super.函数名(注意:1.调用是在子类函数中调用 2.实例的方法不能在字符串模板中执行)
                // Student2 mystudent2 = Student2();
                //  mystudent2.myPrint();
                //print22 //student2
                // print('mystudent2:${mystudent2.myPrint}');
              //(2)子类调用父类构造函数包含主构造函数和命名构造函数
                //注意:
                  //1.调用主构造函数和命名构造函数的区别,主构造函数直接:super(参数),命名构造函数:super.mingmin(参数)
                  // Student4 mystudent4 = Student4('chen',77);
                  // mystudent4.printstr();
                  // print-name:chen;mynum:77
                  //2.若父类没有默认构造函数,需要手动调用其他父类构造函数
                  // Person5 myperson5 = Person5.getDemo('ming',88);//实例化会执行:父类命名构造函数初始化执行方法
                  // print('mypserson5:${myperson5.name}');
                  //子类命名构造函数调用父类命名构造函数
                  // Student51 myStudent51 = Student51.getDemo('hong',99);//实例化会执行:子类命名构造函数调用父类命名构造函数
                  // print('myStudent51:${myStudent51.name}');

            //7.重写父类方法:重写的函数前用@override修饰
              // Student6 mystudent6 = Student6('hua');
              // mystudent6.printName();//重写name:hua
            
            //8.多类继承在继承的第一个父类后跟with,with后跟其他父类,多个父类用逗号隔开
              //注意:1.使用with的各个父类不能加主构造函数声明,否则报错 2.相同的函数名会被覆盖
              // HuaWei myHuaWei = HuaWei('hua');
              // myHuaWei.startPhone();//打开苹果手机:只显示最后一个的原因是startPhone函数名相同,后面的把前面的覆盖了
              
              //不重名时都会执行
              // HuaWei myHuaWei1 = HuaWei('hua');
              // myHuaWei1.startPhone();

        },
        color: Colors.tealAccent,
        child: Text('茶色按钮'),
      ),
      RaisedButton(
        onPressed: () {},
        color: Colors.redAccent,
        child: Text('红色色按钮'),
      ),
      RaisedButton(
        onPressed: () {},
        color: Colors.white,
        child: Text('白色色按钮'),
      ),
    ]);
  }
}

//class类
  //2.面向对象中的变量,搜索:--指向外面类
    //(1).getter setter属性-类似vue中computed属性
    // class Rectangle {
    //   num left, top, width, height;

    //   Rectangle(this.left, this.top, this.width, this.height);

    //   set right(num value) => left = value - width; //使用set作为前缀，只接收一个参数value
    //   set bottom(num value) => top = value - height; //使用set作为前缀，只接收一个参数value
    //   get square => width * height; //getter函数计算面积，描述Rectangle状态特性
    //   bool draw() {
    //     print('draw rect'); //draw绘制函数，触发是动作行为
    //     return true;
    //   }
    // }
    
    //(2).实例变量,分为普通变量和私有变量(用_开头),(并没有发现私有变量和普通变量有何差别)

    class TestBianLiang {
      num total;
      String _str1;
      // TestBianLiang(this.total,this._str1);
      TestBianLiang(this.total,this._str1);
    }
    //(3).final常量,即初始化后就不能改变的变量,特点:1.只有getter函数,没有setter函数
    class FinalDemoClass {
      final String mywant;
      num total;
      FinalDemoClass(this.mywant,this.total);
    }
    //(4).常量对象,特点:1.声明,实例,构造函数都要用const声明 2.常量构造函数必须是数字,字符串,布尔值(所以需要用const声明),且函数不能有函数体,但可以有初始化列表
    class ConstDemo {
      final String name;
      const ConstDemo(this.name);
    }

  //3.构造函数
    //(1).主构造,特点:1.一般默认柱构造函数和类名相同 2.如果没有声明主构造函数,会默认给一个和类名同名的无参构造函数 3.主构造函数不支持重载(即不能重复声明)
    class MainFun {
      String name;
      //1.若这样不写构造函数,会默认加一个无参默认构造函数即 MainFun()

      //2.声明构造函数
      MainFun(this.name);

      //3.若再加一个 MainFun() 会报错

    }
    //补充:初始化实例变量的的几种方式
        //1.变量声明时直接默认赋值
          // class Point {
          //   num x=1,y=2;

          // }

        //2.构造函数初始化
          // class Point {
          //   num x,y;
          //   Point(this.x,this.y);
          // }

        //3.使用初始化列表初始化
          class Point {
            num x,y;
            Point(num a,num b):x=a,y=b;//后跟初始化列表
          }
        //4.在构造函数里初始化
          // class Point {
          //   num x,y;
          //   Point(num a,num b){
          //     x=a;
          //     y=b;
          //   }
          // }

    //2.命名构造函数,组成:类名.函数名 作用:1.为了解决主构造函数不能重载(实际上普通函数也不能重载),有时候需要指定不同构造函数来创建实例问题
      class MingMin {
        String name;
        num total;
        MingMin(this.name,this.total);
        // MingMin.getDemo(this.name);//通过类名.函数名来定义命名构造函数
        //命名构造函数初始化的另一种写法
        MingMin.getDemo(name):name=name{
          print('命名构造函数初始化会执行:$name');
        }

      }
    
    //3.重定向构造函数,将一个构造函数定向到另外一个函数中,':'后是被定向到的目标构造函数
      class ResetFun {
        // String name;
        // num index;
        // ResetFun(this.name,this.index);
        // ResetFun.getDemo(String name,num index):this(name,index);//注意这里this指向到ResetFun(String name,num index)主构造函数中
        
        //或者
        // String name;
        // num index;
        // ResetFun.getDemo(this.name);
        // ResetFun(String name,num index):this.getDemo(name);//注意this,:后不用写数据类型
      }

    //4.函数实例工厂:简而言之为了提升性能把构造函数创建的实例存起来,下次需要时直接从缓存中取
      //关键点:(1)用factory 修饰构造函数 (2)使用命名构造函数 (3)在主构造函数中进行逻辑判断,使用static 关键字声明存储实例的map
      class FactoryDemo {
        final String name;
        //声明存储实例的类map
        static final Map<String,FactoryDemo> _catch = <String,FactoryDemo>{};
        factory FactoryDemo(String name){
          if(_catch.containsKey(name)){//如果存在则返回
          print('直接从缓存中拿;_catch:${_catch.values}');
            return _catch[name];
          }else{//如果不存在则使用命名构造函数创建实例
            FactoryDemo myFactoryDemo = FactoryDemo.getDemo(name);
            print('第一次创建实例');
            _catch[name] = myFactoryDemo;
            return myFactoryDemo;//不光存起来还得返回
          }
        }
        //命名构造函数
        FactoryDemo.getDemo(this.name);
      }

    

  //4.抽象方法,抽象类,接口
    //(1).抽象类抽象方法是用abstract修饰的方法和类,抽象方法包括普通方法,getter,setter即只对其进行声明,并没有具体提供具体的实现
      abstract class Person11 {
        String getName();//抽象普通方法 注意:当类名前用abstract修饰时,抽象的方法或getter,setter前不用加abstract修饰
        get age;//抽象类
      }  

      abstract class Person {//abstract声明抽象类
        String name();//抽象普通方法
        get age;//抽象getter
      }

      class Student extends Person {
        @override//继承后重写抽象的方法
        String name(){
          return '222';
        }
        @override//继承后重写抽象的getter
        get age => null;
        
        
      }
    
    //(2)接口:在dart中每个类都隐含的定义了一个接口,所以dart中并没有关键字interface;interface(目前理解使用类型于extends继承,只是接口可以继承多个类(implements))
    abstract class Specking {
      String speck();
    }
    abstract class Writing {
      String write();
    }
    //student1继承多个类
    class Student1 implements Specking,Writing {
      @override
      speck(){
        return 'i can specking';
      }
      @override
      write(){
        return 'i can writing';
      }
    }
  
  //5.类函数
    //(1)特点:类函数不会被继承;类函数需要用关键字static 修饰 ;类函数直接使用(类名.函数名调用)
    class Car {
      String name;
      num price;
      num shu;
      Car(this.name,this.price,this.shu);
      static String calcTotal(num price,num shu){
        return '总价格:${price * shu}';
      }
    }
    // class Benci extends Car {
    //   String addr;
    //   Benci(this.addr);
    // }

  //6.类继承补充
    //(1)子类调用父类方法:super.函数名
      class Person2 {
        void myPrint(){
          print('print22');
        }
      }
      class Student2 extends Person2 {
        void myPrint(){
          super.myPrint();
          print('student2');
        }
      }
    //(2)子类调用父类构造函数包含主构造函数和命名构造函数
      //注意:
        //1.调用主构造函数和命名构造函数的区别,主构造函数直接:super(参数),命名构造函数:super.mingmin(参数)
          class Person4 {
            String name;
            int mynum;
            Person4(this.name,this.mynum);
            printstr(){
              print('print-name:$name;mynum:$mynum');
            }
          }
          class Student4 extends Person4 {
            String name;
            int mynum;
            //子类构造函数重定向到父构造函数,调用父构造函数实例化
            Student4(this.name,this.mynum):super(name,mynum);
          }
        //2.若父类没有默认构造函数,需要手动调用其他父类构造函数
          //注意:(1).命名构造函数不会传递不会被继承,所以当父类没有主构造函数时,需要手动调用其他构造函数
               //(2).调用父类构造函数可以通过:1子类主构造函数重定向到父类其他构造函数 2.通过子类命名构造函数列表初始化后跟super.父类命名构造函数名

          class Person5 {
            String name;
            int mynum;
            //命名构造函数不会传递不会被继承
            Person5.getDemo(name,mynum):name=name,mynum=mynum{
              //实例化的时候会执行这里面的方法
              print('父类命名构造函数初始化执行方法');
            }
          }
          class Student5 extends Person5 {
            String name;
            int mynum;
            //命名构造函数不会传递不会被继承,所以当父类没有主构造函数时,需要手动调用其他构造函数
            Student5(this.name,this.mynum):super.getDemo(name,mynum){
              print('子类主构造函数重定向到父类命名构造函数');
            }
          }
          class Student51 extends Person5 {
            String name;
            int mynum;
            //通过子类命名构造函数列表初始化后跟super.父类命名构造函数名
            Student51.getDemo(name,mynum):name=name,mynum=mynum,super.getDemo(name,mynum){
              print('子类命名构造函数调用父类命名构造函数');
            }
          }

  //7.重写父类方法:重写的函数前用@override修饰
   class Person6 {
     String name;
     Person6(this.name);
     void printName(){
       print('person6-name:$name');
     }
   }
   class Student6 extends Person6 {
     String name1;
     Student6(this.name1):super(name1);
     @override
     void printName(){
       print('重写name:$name');
     }
   }

  //8.多类继承在继承的第一个父类后跟with,with后跟其他父类,多个父类用逗号隔开
    class Phone {
      // String name;
      // Phone(this.name);
      void startPhone1(){
        print('打开phone');
      }
    }
    class AndroidPhone{
      // String name;
      // AndroidPhone(this.name);
      void startPhone2(){
        print('打开安卓手机');
      }
    }
    class IosPhone{
      // String name;
      // IosPhone(this.name);
      void startPhone3(){
        print('打开苹果手机');
      }
    }
    class HuaWei extends Phone with AndroidPhone,IosPhone {
      String name;
      HuaWei(this.name);
      void startPhone(){
        // super.startPhone();
        super.startPhone1();
        super.startPhone2();
        super.startPhone3();
        print('打开华为手机');
      }
    }
  class Rectangle {
    num left,top,width,height;
    Rectangle(this.left,this.top,this.width,this.height);
    set right(num val)=> left =val-width;//20-3
    set bottom(num val)=>top=val-height;//2-4
    get square =>left * top;
    // get square =>width * height;
    bool draw(){
      print('draw rect');
      return true;
    }
  }


//水平布局灵活
class MyExpanded extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Expanded(
            child: RaisedButton(
          onPressed: () {},
          color: Colors.tealAccent,
          child: Text('茶色按钮'),
        )),
        RaisedButton(
          onPressed: () {},
          color: Colors.redAccent,
          child: Text('红色色按钮'),
        ),
        Expanded(
            child: RaisedButton(
          onPressed: () {},
          color: Colors.white,
          child: Text('白色色按钮'),
        ))
      ],
    );
  }
}

//纵向布局 和静态图片使用
class MyColumnContainer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Text('aaaaa'),
        Image.asset('image/back.png'),
        Expanded(
          child: Container(
            child: Text('bbbb'),
            width: 50.0,
            decoration: BoxDecoration(
                gradient: const LinearGradient(colors: [
              Colors.lightGreen,
              Colors.limeAccent,
              Colors.deepPurple
            ])),
            alignment: Alignment.center,
          ),
        ),
        Text('啊啊大大大方法封 方法 方法')
      ],
      // crossAxisAlignment:CrossAxisAlignment.start, //默认以最宽的盒子为基准居中
      mainAxisAlignment: MainAxisAlignment.center,
    );
  }
}

//重叠布局
class MyStackContainer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        CircleAvatar(
            backgroundImage: NetworkImage(
                'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2463832682,707578156&fm=26&gp=0.jpg'),
            radius: 100.0),
        Positioned(
          child: Container(
              padding: const EdgeInsets.all(5.0),
              decoration: BoxDecoration(
                color: Colors.transparent,
              ),
              child: Text('科学家',
                  style: TextStyle(fontSize: 30.0, color: Colors.black))),
          bottom: 10.0,
          right: 50.0,
        ),
        Positioned(
            child: CircleAvatar(
              backgroundImage: NetworkImage(
                  'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2073768005,2909626268&fm=26&gp=0.jpg'),
              radius: 20.0,
            ),
            bottom: 70.0,
            right: 70.0)
        //left: MediaQuery.of(context).size.width / 2 - 35,  --计算 类似于css中calc
      ],
      alignment: const FractionalOffset(0.5, 0.8), //两个容器是定位,多个定位用position
    );
  }
}

//卡片组件
class MyCard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Card(
        child: Column(children: <Widget>[
      ListTile(
        title: Text('贵州省贵阳市'),
        subtitle: Text('刘铁柱:14555577'),
        leading: Icon(Icons.ac_unit_outlined),
      ),
      Divider(),
      ListTile(
        title: Text('贵州省贵阳市'),
        subtitle: Text('刘铁柱:14555577'),
        leading: Icon(Icons.ac_unit_outlined),
      ),
      Divider(),
      ListTile(
        title: Text('贵州省贵阳市'),
        subtitle: Text('刘铁柱:14555577'),
        leading: Icon(Icons.ac_unit_outlined),
      ),
      Divider(),
      ListTile(
        title: Text('贵州省贵阳市'),
        subtitle: Text('刘铁柱:14555577'),
        leading: Icon(Icons.ac_unit_outlined),
      ),
      Divider(),
      ListTile(
        title: Text('贵州省贵阳市'),
        subtitle: Text('刘铁柱:14555577'),
        leading: Icon(Icons.ac_unit_outlined),
      ),
    ]));
  }
}

//页面跳转和返回
class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: RaisedButton(
          onPressed: () {
            Navigator.push(context,
                MaterialPageRoute(builder: (context) => SecondScreen()));
          },
          child: Text('跳转'),
          color: Colors.redAccent),
    );
  }
}


class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('返回'),
          color: Colors.deepPurple),
    );
  }
}


class ProductList extends StatelessWidget {
  final List<Product> products;
  const ProductList({Key key, @required this.products}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('商品列表'),
      ),
      body: Container(
        child: ListView.builder(
            itemCount: products.length,
            itemBuilder: (context, index) {
              return Card(
                child: Column(
                  children: <Widget>[
                    Divider(),
                    ListTile(
                      title: Text('${products[index].title}'),
                      subtitle: Text('${products[index].description}'),
                      leading: Icon(Icons.backpack_outlined),
                      onTap: () {
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) =>
                                    ProductDetail(product: products[index])));
                      },
                    ),
                  ],
                ),
              );
            }),
      ),
    );
  }
}

class ProductDetail extends StatelessWidget {
  final Product product;
  const ProductDetail({Key key, @required this.product}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('${product.title}'),
        ),
        body: Column(
          children: <Widget>[
            Text('${product.title}', style: TextStyle(color: Colors.redAccent)),
            Text('${product.description}',
                style: TextStyle(color: Colors.lightBlueAccent))
          ],
        ));
  }
}

//页面跳转,返回携带数据
class MyFirstPage extends StatelessWidget {
  final List<Product> products;
  MyFirstPage({Key key, @required this.products}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('首页'),
        ),
        body: ListView.builder(
          itemCount: products.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text('${products[index].title}'),
              subtitle: Text('${products[index].description}'),
              leading: Icon(Icons.description_rounded),
              onTap: () => {_navigatorDetailInfo(context)},
            );
            // return Container(child: RouteButton());
          },
        ));
  }

  //和Widget同级
  _navigatorDetailInfo(BuildContext context) async {
    final result = await Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => MyDeitail(
                products:
                    products) //跳转到另一个页面中,等待点击获取结果后(页面返回Navigator.pop(context,data))才执行下列代码
            ));
    // Scaffold.of(context).showSnackBar(SnackBar(content: Text('$result')));
    Scaffold.of(context).showSnackBar(SnackBar(content: Text('$result')));
  }
}

class MyDeitail extends StatelessWidget {
  final List<Product> products;
  MyDeitail({Key key, @required this.products}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("详情页"),
      ),
      body: Center(
        child: ListView.builder(
            itemCount: products.length,
            itemBuilder: (context, index) {
              // return ListTile(
              //   title: Text('${products[index].title}'),
              //   leading: Icon(Icons.title_outlined),
              //   onTap: ()=>{
              //     Navigator.pop(context,'${products[index].title},电话:12234566')
              //   },
              // );
              return Column(
                children: <Widget>[
                  ListTile(
                      title: Text('${products[index].title}'),
                      leading: Icon(Icons.title_outlined),
                      onTap: () => {
                            Navigator.pop(
                                context, '${products[index].title},电话:12234566')
                          }),
                  Divider()
                ],
              );
            }),
      ),
    );
  }
}
